首页 \ 问答 \ Spray REST API应用程序结构 - 需要建议(Spray REST API Application Structure - Suggestions Needed)

Spray REST API应用程序结构 - 需要建议(Spray REST API Application Structure - Suggestions Needed)

我有以下使用sbt构建的多模块项目结构:

myProject-api
myProject-core

myProject-core的组织如下:

它包含某些演员作为我的服务的外观。 例如,我有一个位于UserService前面的UserActor。 位于NotificationService之前的NotificationActor等。

我有另一个特征,让任何感兴趣的人暴露于演员:

trait MyProjectCoreActors {

  def myAppCfg = MyProjConfig.appCfg      

  def userActor = myAppCfg.userActor
  def notifyActor = myAppCfg.notifyActor
}
object MyProjectCoreActors {

  ... some initialization routing that initializes the MyProjConfig
}

我的UserActor因此被定义为:

class UserActor(service: UserService) extends Actor {

  ...
  ...
}

我的UserService如下所示:

class UserService(dbConfig: DbConfig) {

  ...
  ...
}

我有另一个名为MyProjectConfig的类,我使用application.conf文件进行初始化。 在这个文件中,我有连接细节到数据库等等。 MyProjectConfig初始化如下:

trait MyProjectConfig {

  def actorSystem: ActorSystem

  // the actors
  def userActor: ActorRef
}
object MyProjectConfig {

  def apply(appConfig: Config, system: ActorSystem): MyProjectConfig = {

    new MyProjectConfig {
      private val dbConfig = loadDBConfig(appConfig)

      override val actorSystem = system

      // each actor gets its own DBConfigInstance instance
      override val userActor =
        actorSystem.actorOf(
          Props(new UserActor(UserService(dbConfig)))
        )
    }
  }
}

我现在有如下定义的喷涂路线:

trait MyProjectService extends HttpService with MyProjectCoreActors {

  def pingRoute = path("ping") {
    get {
      userActor ! "newUser"
      complete("pong!")
    }
  }

  def pongRoute = path("pong") {
    get { complete("pong!?") }
  }

  def route = pingRoute ~ pongRoute
}

现在缺少的是一种调用MyProjectConfig.apply(....)方法并传入Actor系统和底层application.conf的方法!

这本来是一个基于Play的应用程序,我有一个Lifecycle插件,可以从我获得配置和actor系统访问底层应用程序。 我现在怎么能和Spray一样呢?

我有一个Boot类,看起来像这样:

object MyBootHttpService extends App {

  implicit val actorSystem = ActorSystem("myproj-actor-system")

}

我怎么能把这个ActorSytem传递给MyProjectConfig.apply(....)? 并从哪里可以得到application.conf?


I have the following multi-module project structure built using sbt:

myProject-api
myProject-core

myProject-core is organized as below:

It contains certain actors which acts as a facade to my services. For example., I have a UserActor that sits in front of a UserService. A NotificationActor that sits in front of a NotificationService and so on.

I have another trait that exposes there actors to anybody that is interested:

trait MyProjectCoreActors {

  def myAppCfg = MyProjConfig.appCfg      

  def userActor = myAppCfg.userActor
  def notifyActor = myAppCfg.notifyActor
}
object MyProjectCoreActors {

  ... some initialization routing that initializes the MyProjConfig
}

My UserActor is thus defined as:

class UserActor(service: UserService) extends Actor {

  ...
  ...
}

My UserService is as follows:

class UserService(dbConfig: DbConfig) {

  ...
  ...
}

I have another class called MyProjectConfig which I initialize using the application.conf file. In this file I have the connection details to the database and so on. The MyProjectConfig is initialized as below:

trait MyProjectConfig {

  def actorSystem: ActorSystem

  // the actors
  def userActor: ActorRef
}
object MyProjectConfig {

  def apply(appConfig: Config, system: ActorSystem): MyProjectConfig = {

    new MyProjectConfig {
      private val dbConfig = loadDBConfig(appConfig)

      override val actorSystem = system

      // each actor gets its own DBConfigInstance instance
      override val userActor =
        actorSystem.actorOf(
          Props(new UserActor(UserService(dbConfig)))
        )
    }
  }
}

I have now the Spray routing as defined below:

trait MyProjectService extends HttpService with MyProjectCoreActors {

  def pingRoute = path("ping") {
    get {
      userActor ! "newUser"
      complete("pong!")
    }
  }

  def pongRoute = path("pong") {
    get { complete("pong!?") }
  }

  def route = pingRoute ~ pongRoute
}

What is now missing is a way to call the MyProjectConfig.apply(....) method and pass in the Actor System and the underlying application.conf!

This was originally a Play based application, where I had a Lifecycle plug in which had access to the underlying Application from where I got the config and the actor system. How could I now get the same here with Spray?

I have a Boot class that looks like this:

object MyBootHttpService extends App {

  implicit val actorSystem = ActorSystem("myproj-actor-system")

}

How could I pass this ActorSytem to MyProjectConfig.apply(....)? and from where could I get the application.conf?


原文:https://stackoverflow.com/questions/33570741
更新时间:2023-09-04 07:09

最满意答案

这是一个奇怪的问题,我怀疑这是Dymola的一个错误(原因我会在一秒钟内解释)。

事实证明你遇到了这个问题 ,虽然在这种情况下根本不明显为什么会出现这种情况。

因此,一种解决方案是使用稍微不同的Timer模型实现,如下所示:

block Timer 
  "Timer measuring the time from the time instant where the Boolean input became true" 

  extends Modelica.Blocks.Interfaces.partialBooleanBlockIcon;
  Modelica.Blocks.Interfaces.BooleanInput u "Connector of Boolean input signal"
    annotation (extent=[-140,-20; -100,20]);
  Modelica.Blocks.Interfaces.RealOutput y "Connector of Real output signal" 
    annotation (extent=[100,-10; 120,10]);
protected 
  discrete Modelica.SIunits.Time entryTime "Time instant when u became true";
initial equation 
  pre(entryTime) = 0;
equation 
  when pre(u) then
    entryTime = time; 
  end when;
  y = if u then time - entryTime else 0.0;
end Timer;

注意在when子句中围绕条件存在pre运算符。

一般来说,使用pre运算符是一个好主意(正如我在其他问题中解释的那样 )。 为什么有必要在你的具体情况下,我无法解释。 条件表达式在您的情况下是true ,这意味着它应该在模拟开始when触发when子句。 我没有看到Dymola在这里谈论的代数循环。 我怀疑它与Dymola有关,试图组织在模拟开始时应该发生的所有事情,并在那里遇到一些复杂问题。 但它并不明显,我提到的替代Timer模型都可以避免这一切。


This is strange problem and I suspect this is a bug in Dymola (for reasons I will explain in a second).

It turns out you are running into this issue, although it isn't at all obvious in this situation why this should be the case.

So one solution is to use a slightly different implementation of the Timer model, one that looks like this:

block Timer 
  "Timer measuring the time from the time instant where the Boolean input became true" 

  extends Modelica.Blocks.Interfaces.partialBooleanBlockIcon;
  Modelica.Blocks.Interfaces.BooleanInput u "Connector of Boolean input signal"
    annotation (extent=[-140,-20; -100,20]);
  Modelica.Blocks.Interfaces.RealOutput y "Connector of Real output signal" 
    annotation (extent=[100,-10; 120,10]);
protected 
  discrete Modelica.SIunits.Time entryTime "Time instant when u became true";
initial equation 
  pre(entryTime) = 0;
equation 
  when pre(u) then
    entryTime = time; 
  end when;
  y = if u then time - entryTime else 0.0;
end Timer;

Note the presence of the pre operator around the condition in the when clause.

In general, the use of the pre operator is a good idea (as I explain in that other issue). Why it is necessary in your specific case, I cannot explain. The conditional expression is simply true in your case which means it should trigger the when clause at the start of simulation. I don't see the algebraic loop that Dymola is talking about here. I suspect it has something to do with Dymola trying to organize all the things that should happen at the start of the simulation and running into some complication there. But it isn't obvious and it can all be avoided with the alternative Timer model I mentioned.

相关问答

更多
  • Modelica语言规范3.4(第11.1.2节)说: 使用其起始值(即start-attribute的值)初始化非离散变量。 离散变量v用pre(v)初始化。 如果数组中至少有一个元素出现在赋值运算符的左侧,则在此算法部分中初始化完整数组。 [...] 算法部分被视为原子矢量方程,它与所有其他方程一起排序。 因此,所有变量都将使用算法块每次执行开始时的起始值进行初始化。 没有内存,预变量等,所以如果你在if语句中赋值变量,这个值将在下一次执行该段时丢失。 造成这种情况的部分原因是并不总是知道分配了哪些索引 ...
  • 请参阅HideResult注释: https ://modelica.org/documents/ModelicaSpec33Revision1.pdf subsystem subsystem1 annotation(HideResult = true / false); See HideResult annotation: https://modelica.org/documents/ModelicaSpec33Revision1.pdf subsystem subsystem1 annotation( ...
  • 你的交错网格很好,你可以设置你需要的地方。 别担心,这不是你的错,是调试,我试过多次使用它,它总是以其中一种方式失败(我不知道你的适配器的位置,但它并不重要)。 您可以随时使用定义关系dp(Areas_rate)的孔,避免两种情况下的反转流,因此在孔之前和之后连接两个体积(如两个并联的阀门)。 这应该工作。 your staggered grid is fine, you set volumes where you had to. Don't worry, it's not your fault, is a ...
  • 不,因为y和x被声明为条件,4.4.5包含语句“使用条件属性声明的组件只能在连接中修改和/或使用”。 没有特殊规则可以从if语句的分支中删除它们。 No, since y and x are declared conditional and 4.4.5 includes the statement "A component declared with a condition-attribute can only be modified and/or used in connections". There i ...
  • 这在Modelica规范的“4.7平衡模型”一节中描述。 问题是腔室有一个顶层连接器conn ,还有一个与之相关的方程式; 例如conn.massRate=0; 对应于分层模型中的默认连接连接器。 它不仅是一个方程太多 - 它也是错误的。 此外,如果您使用Chamber作为子模型,并且想要将外部流量添加到腔室中,则可以连接到conn - 但方程式没有意义。 当您将反应器移出腔室时,您可以避免悬挂连接器。 另一个可能更清晰的替代方案是拥有两个模型,例如: model Chamber Reactio ...
  • 假设最初turn = 0 。 P0执行其临界部分并设置turn = 1 。 现在,P1 必须在P0再次执行它之前执行它的临界区 。 但是,仅仅因为两个线程都有一个关键部分并不意味着他们想要以这种方式来替换它们的使用 - 事实上,P1可能永远不会轮到它。 (在一般情况下,你不能在编译时确定它 。) 所以基本上问题是线程被迫轮流轮换 ,即使其中一个线程实际上不想无限期地进入临界区域。 顺便说一下,您对问题1的回答是正确的。 该算法不会失败进度条件,它会失败有界等待条件。 Suppose that turn = ...
  • 你是对的。 我很确定这将是OpenModelica中的一个错误。 该模型的工作方式与您在Dymola 2013中的预期相同。 我的猜测是,它与你的条件涉及x和内部语句最终改变x (同一个变量)的事实有关。 它可能是某种程度上没有注意到用于确定when子句应该触发的点的监视器函数中的重新启动。 You are correct. I am pretty sure this would be a bug in OpenModelica. The model works as you would expect in ...
  • 这是一个奇怪的问题,我怀疑这是Dymola的一个错误(原因我会在一秒钟内解释)。 事实证明你遇到了这个问题 ,虽然在这种情况下根本不明显为什么会出现这种情况。 因此,一种解决方案是使用稍微不同的Timer模型实现,如下所示: block Timer "Timer measuring the time from the time instant where the Boolean input became true" extends Modelica.Blocks.Interfaces.part ...
  • algorithm部分和equation部分之间的主要区别在于equation部分中的每个方程都用于模拟模型。 使用algorithm部分,您有必要的赋值语句。 这意味着您可以覆盖之前作业的影响。 作为一个具体的例子,在下面的equation部分: equation a = b; a = c; 有两个等式。 每个都会被使用。 另一方面,如果我有以下algorithm部分 algorithm a := b; a := c; 第二个任务总是否定第一个任务。 但是,让我添加一些“大图”来帮助您 ...
  • 你需要使用when ,而不是if 。 您可以通过示例在Modelica中找到关于它们和它们之间的差异的讨论。 此问题也已在此处和此处进行了讨论。 这是一个例子(完全未经测试,但它显示了基本想法): model HighWaterMarkPerInterval extends Modelica.Blocks.Interfaces.SISO; parameter Modelica.SIunits.Time sample_rate=3600; Real flybyEnds[45] = {3081315 ...

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。